//***********************************************************
//*
//* File:           DumbPlayer.java
//* Author:         Abhinav Kamra
//* Contact:        kamra@cs.columbia.edu
//* Update:         10/03/2004
//*
//* Description:    Dump player for Project 2.  Purely for
//*                 didactic purposes.
//*
//***********************************************************

package paths.G4Player;

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;

import paths.*;
import ui.Util;

public final class G4Player implements IFCPlayer {

    static Random _random;
    static final String _CNAME = "G4 Player";
    static final Color  _CCOLOR = new Color(0.8f, 0.2f, 0.4f);

    Maps _maps;
    ArrayList<City> cities;
    ArrayList<Link> links;

    public final class LinkDirection
    {
        public String src, dest, schedule;	
        public int direction = 0;  //0: same longitute, 1: east, 2: west
 
        public LinkDirection( Link link) throws Exception
        {
        	src = link.src;		    
        	dest = link.dest;
        	schedule = link.schedule;
        	
        	int maxLong = 900;

        	City source, destination;
        	//tell the direction
        	source = getCityByName(src);
        	destination = getCityByName(dest);
        	if(source.x == destination.x)
        		direction = 0;
        	else if((source.x>destination.x && source.x-destination.x<maxLong/2)
        		||	(source.x<destination.x && destination.x-source.x>maxLong/2)) 
        	{
        		direction = 2;   //west
        	}
        	else
        		direction = 1;   //east  
        	
        }
    }
    ArrayList<LinkDirection> linkDirs = new ArrayList<LinkDirection>();

    public final class LinkCity
    {
    	ArrayList<String> linkedCity = new ArrayList<String>() ;    	
    }
    ArrayList<LinkCity> eastCity = new ArrayList<LinkCity>();
    ArrayList<LinkCity> westCity = new ArrayList<LinkCity>();

    public final class CityToStart
    {
    	String city;   
    	int distance;
    	int flag;  
    	//0: ; 
    	//1,2:east/west within the edges, langitude larger/smaller ; 
    	//3,4:east/west outside, langitude smaller/larger than start 
    	ArrayList<String> citiesConnect;   
    	public CityToStart(){
    		city = new String();
    		distance = 0;
    		citiesConnect = new ArrayList<String>() ;
//    		citiesConnect.add(o);
    	}
    	
    	public CityToStart(String cityself){
    		city = new String(cityself);
    		distance = 0;
    		citiesConnect = new ArrayList<String>() ;
    	}
    	
    	public CityToStart(String cityself, int dis){
    		city = new String(cityself);
    		distance = dis;
    		citiesConnect = new ArrayList<String>() ;
    	}
    }
    ArrayList<CityToStart> allCity = new ArrayList<CityToStart>();

    //    TimeFunction timeFunction;
    public void register(Maps __maps) throws Exception {
	    _maps = __maps;
	    cities = _maps.getCities();
	    links = _maps.getLinks();
	    //timeFunction = _maps.getTimeFunction();
    }

    public Move move() throws Exception {
    	
    	//test
        ArrayList<Link> test = new ArrayList<Link>() ;
        Link t1 = new Link("a b 3");        
        test.add(t1);
        
    	
	    BufferedImage image;

	    File file = _maps.getBackgroundImage();
	    
	    //to get the background image, do this
	    image = ImageIO.read(file);
	    
	    //get graphics to draw on the image.
	    Graphics2D g = image.createGraphics();

	    int temp = 0;
	if(temp == 1){

		g.setColor(Color.BLUE);
	    Iterator<Link> itLink = links.iterator();
	    //System.out.println("Travel times at midnight:");
	    while(itLink.hasNext()){
	    	Link l = itLink.next();
	    	System.out.println(l.src + " to "+l.dest);
	    	City src = getCityByName(l.src);
	    	City dest = getCityByName(l.dest);
	    	//g.drawLine(src.x, src.y, dest.x, dest.y);
	    }
		
		g.setFont(new Font(g.getFont().getName(), Font.BOLD, 18));
   	    
	    Iterator<City> itCity = cities.iterator();
	    while(itCity.hasNext()){
	    	City city = itCity.next();
	    	System.out.println(city.name);
	    	if(_maps.getStart().equals(city)){
	    		g.setColor(Color.RED);
	    		g.drawString("Start: "+city.name, city.x, city.y);		    		
	    	}else{
	    		g.setColor(Color.GREEN);
	    		g.drawString(city.name, city.x, city.y);
	    	}
	    }

	}
	else{

		g.setColor(Color.BLUE);
	    Iterator<Link> itLink = links.iterator();
	    //System.out.println("Travel times at midnight:");
	    while(itLink.hasNext()){
	    	Link l = itLink.next();
	    	
	    	System.out.println(l.src + " to "+l.dest);
	    	City src = getCityByName(l.src);
	    	City dest = getCityByName(l.dest);
	    	
	    	LinkDirection lDir;
	    	lDir = new LinkDirection(l);
	    	linkDirs.add( lDir );
	    	
	    	if(lDir.direction == 2){
	    		//west
	    		g.setColor(Color.BLUE);
		    	//g.drawLine(src.x, src.y, dest.x, dest.y);
	    	}
	    	if(lDir.direction == 1){
	    		//east
	    		g.setColor(Color.BLACK);
		    	//g.drawLine(src.x, src.y, dest.x, dest.y);
	    	}
//	    	g.drawLine(src.x, src.y, dest.x, dest.y);
	    }
	    //end of link
	    
	    g.setFont(new Font(g.getFont().getName(), Font.BOLD, 18));
		
	    Iterator<City> itCity = cities.iterator();
	    while(itCity.hasNext()){
	    	City city = itCity.next();
//	    	System.out.println(city.name);
	    	
	    	findLink(city.name);
	    	//need to move after the following linkDirs
		    Iterator<LinkCity> itCity2 = eastCity.iterator();
		    while(itCity2.hasNext()){
		    	LinkCity city2 = itCity2.next();
		    	if (city2.linkedCity.get(0).equalsIgnoreCase(city.name)){
		    		//same city
		    		for (int i=0; i<city2.linkedCity.size(); i++)
		    	    	System.out.println(city2.linkedCity.get(i));
		    	}
		    }
//	    	System.out.println("4");
	    	
	    	
	    	if(_maps.getStart().equals(city)){
	    		g.setColor(Color.RED);
	    		g.drawString("Start: "+city.name, city.x, city.y);		    		
	    	}else{
	    		g.setColor(Color.GREEN);
	    		g.drawString(city.name, city.x, city.y);
	    	}
	    }  //end of city
	    
	    //begin of check distance
	    String startCity = _maps.getStart().name;
	    
	    CityToStart start = new CityToStart(startCity, 0);
	    start.flag = 0; //start
	    allCity.add(start);
	    
	    //tag all the west links with distance
	    tagDist(startCity, 0, startCity, 0);

	    /*
	    int dist = 0;
	    String end = new String(startCity);
	    String startName = new String(startCity);
	    String newCity = new String();
	    Iterator<LinkCity> itEastCity = eastCity.iterator();
	    Iterator<CityToStart> itCity3 = allCity.iterator();
	    LinkCity newEastCity = new LinkCity();

	    while(itEastCity.hasNext()){
	    	LinkCity city = itEastCity.next();
	    	if (city.linkedCity.get(0).equalsIgnoreCase(startName)){
	    		dist ++;
	    		for (int i=1; i<city.linkedCity.size();i++){
		    		newCity = city.linkedCity.get(i);
		    		itCity3 = allCity.iterator();
		    	    while(itCity3.hasNext()){
		    	    	CityToStart city2 = itCity3.next();
		    	    	if (city2.City.get(0).equalsIgnoreCase(newCity)){
		    	    		if(city2.distance < dist){
		    	    			start = new CityToStart(newCity, dist);
		    	    			allCity.add(start);
		    	    		}
		    	    		else if(city2.distance == dist){
		    	    			city2.City.add(startCity);
		    	    		}
		    	    		else if(city2.distance > dist){
		    	    			//do nothing
		    	    		}		    	    		
		    	    	}
		    	    }
	    		}
	    			
	    	}
	    }
	    */
	    //draw one route from start to start
//	    Iterator<CityToStart> itCity3 = allCity.iterator();
	    String startW = new String(startCity);
	    String newCity = new String();
	    int flag = 1;
	    int temp2 = 0;
	    
	    while(flag == 1){
		    Iterator<CityToStart> itCity3 = allCity.iterator();
	    	System.out.println(temp2);
	    	temp2++;

		    while(itCity3.hasNext()){
		    	CityToStart city2 = itCity3.next();
		    	if (city2.city.equalsIgnoreCase(startW)){
		    		//draw the edge between newCity and the first city
		    		if (city2.citiesConnect.size()==0)
		    		{
		    			flag = 0;
		    			break;		    			
		    		}
		    		newCity = new String(city2.citiesConnect.get(0));
		    		
			    	City src = getCityByName(startW);
			    	City dest = getCityByName(newCity);
		    		g.setColor(Color.RED);
			    	g.drawLine(src.x, src.y, dest.x, dest.y);

			    	startW = new String(newCity);
			    	flag = 2;
			    	if (startW.equalsIgnoreCase(startCity))
			    		flag = 0;
			    	break;
		    	}
		    }
		    
		    if(flag == 1)
		    	flag = 0;
		    else if(flag == 2)
		    	flag = 1;
	    	
	    }  //end of flag

	} //end of if/else, meaning nothing
	

	    Move RET = new Move(image, "Dumb WSF Map");
	    return RET;
    }
    
    
    public void tagDist (String city, int tag, String startCity, int distance)
    {
	    int dist = distance + 1;
	    int newtag = 0;
	    
    	System.out.println(dist + city);
    
//	    String end = new String(startCity);
//	    String startName = new String(startCity);
	    String newCity = new String();
	    
	    Iterator<LinkCity> itWestCity = westCity.iterator();
	    Iterator<CityToStart> itCity3 = allCity.iterator();
	    
//	    LinkCity newEastCity = new LinkCity();

	    while(itWestCity.hasNext()){
	    	LinkCity cityW = itWestCity.next();
	    	if (cityW.linkedCity.get(0).equalsIgnoreCase(city)){
	    		//find the start of this link
	    		for (int i=1; i<cityW.linkedCity.size();i++){
		    		newCity = cityW.linkedCity.get(i);
		    		//end of all the links
		    		
	    	    	City src = getCityByName(city);
	    	    	City dest = getCityByName(newCity);
	    	    	City start = getCityByName(startCity);

		    		//tell the tag of new city
		    		if (tag ==0){
		    	    	//now we are using west direction
		    			if (src.x > dest.x){ //within edge
		    				newtag = 2;  //west
		    			}
		    			else if (src.x < dest.x){ //outside the edge
		    				newtag = 4;  //west
		    			}
		    			else if (src.x == dest.x){ //within edge
		    				return;  //do nothing
		    			}
		    		}
		    		else if(tag ==1){
		    			return;  //only west now
		    		}
		    		else if(tag ==2){
		    			if (src.x > dest.x){ //within edge
		    				newtag = 2;  //west
		    			}
		    			else if (src.x < dest.x){ //outside the edge
		    				newtag = 4;  //west
		    			}
		    			else if (src.x == dest.x){ //within edge
		    				return;  //do nothing
		    			}		    			
		    		}
		    		else if(tag ==3){
		    			return;  //only west now		    			
		    		}
		    		else if(tag ==4){  //already outside edge, only once
		    			if (src.x > dest.x && dest.x > start.x){ //within edge
		    				newtag = 4;  //west
		    			}
		    			else if( newCity.equalsIgnoreCase(startCity)){
		    				//go back to the start
		    				newtag = 5;
		    			}
		    			else{
		    				return;  //do nothing
		    			}		    			
		    			
		    		}
		    		else
		    			return;
		    		
		    		itCity3 = allCity.iterator();
		    		int index=-1;
		    		int flag = 0;
		    	    while(itCity3.hasNext()){
		    	    	CityToStart city2 = itCity3.next();
		    	    	index ++;
	/*	    	    	
		    	    	//find the distance link of start city
		    	    	if (city2.city.equalsIgnoreCase(startCity)){
	    	    			CityToStart start = allCity.get(index);
	    	    			start.citiesConnect.add(newCity);
		    	    	}		    	    	
		*/    	    	
		    	    	//find the distance link of new city
		    	    	if (city2.city.equalsIgnoreCase(newCity)){
		    	    		
		    	    		flag = 1;
		    	    		
	    	    			CityToStart newStart = allCity.get(index);
		    	    		if(city2.distance < dist){
		    	    			//a larger distance
		    	    			//change the dist, and the list
//		    	    			CityToStart start = new CityToStart(newCity, dist);
//		    	    			allCity.add(start);
		    	    			newStart.distance = dist;
		    	    			newStart.citiesConnect = new ArrayList<String>();
		    	    			newStart.citiesConnect.add(city);
		    	    			
		    	    			//recurrsive
		    	    			tagDist(newCity, newtag, startCity, dist);
		    	    		}
		    	    		else if(city2.distance == dist){
//		    	    			city2.citiesConnect.add(city);
		    	    			newStart.citiesConnect.add(city);
		    	    		}
		    	    		else if(city2.distance > dist){
		    	    			return;
		    	    			//do nothing
		    	    		}		    	    		
		    	    	}
		    	    }  //end of while
		    	    
	    	    	if(flag == 0){
	    	    		//don't have this city, new
    	    			CityToStart newStart = new CityToStart(newCity, dist);
    	    			newStart.citiesConnect.add(city);
    	    			allCity.add(newStart);
    	    			//recurrsive
    	    			tagDist(newCity, newtag, startCity, dist);
	    	    	}
		    	    
	    		}
	    			
	    	}
	    }
    	
    }

//    public City getCityByName(String name){
    private City getCityByName(String name){
    	Iterator<City> it = cities.iterator();
    	while(it.hasNext()){
    		City city = it.next();
    		if(name.equalsIgnoreCase(city.name))
    			return city;
    	}
    	return null;
    }
    
    /**
     * check the direction of the link between two cities
     * @param src
     * @param dest
     * @return link type, 0-3: same, east, west, no link
     */
    private int checkLink(String src, String dest){
    	int linkType = 3; //0same, 1east, 2west, 3no link
    	Iterator<LinkDirection> it = linkDirs.iterator();
    	while(it.hasNext()){
    		LinkDirection link = it.next();
    		if(link.src.equalsIgnoreCase(src) && 
    				link.dest.equalsIgnoreCase(dest)	)
    			return link.direction;
    	}
    	return linkType;
    }

    /**
     * 
     * @param src
     */
    private void findLink(String src){
//      private void findLink(String src, int direction){
    	int linkType = 3; //0same, 1east, 2west, 3no link
    	LinkCity linked = new LinkCity();
    	LinkCity west = new LinkCity();
    	linked.linkedCity.add(src);
    	west.linkedCity.add(src);

	    Iterator<City> itCity = cities.iterator();
	    while(itCity.hasNext()){
	    	City city = itCity.next();
	    	if (! city.name.equalsIgnoreCase(src)) {
	    		//different city
//	    		if (checkLink(src, city.name) == direction){
    			// same direction
	    		if (checkLink(src, city.name) == 1){
	    			linked.linkedCity.add(city.name);
	    		}
	    		else if (checkLink(src, city.name) == 2){
		    			west.linkedCity.add(city.name);
	    		}
	    	}
	    }
	    eastCity.add(linked);
	    westCity.add(west);

    }



    public String name() throws Exception {
        return _CNAME;
    }

    public Color color() throws Exception {
        return _CCOLOR;
    }

    public boolean interactive() throws Exception {
        return false;
    }        

}
